import {
    Alert,
    Box,
    Card,
    Checkbox,
    DialogContent,
    DialogTitle,
    Grid,
    ListItemText,
    MenuItem,
    SelectChangeEvent,
    Typography
} from '@mui/material';
import React, { useEffect, useState } from 'react';
import { toast } from 'react-toastify';

import DisbursementManager from '../../api/disbursement/disbursement-manager';
import DisbursementType, { getIDByName } from '../../api/disbursement/disbursement-type';
import PayrollGroup from '../../api/payroll-group/payroll-group';
import PayrollGroupManager from '../../api/payroll-group/payroll-group-manager';
import { GFSLoadingButton } from '../shared/button/gfs-button';
import GFSDialog from '../shared/dialogs/gfs-dialog';
import { useStyles } from '../shared/dialogs/UIs/styled-mui-dialog';
import { GfsInputBase, GfsInputLabel, GfsInputSelectBase } from '../shared/forms';

const ITEM_HEIGHT = 48;
const ITEM_PADDING_TOP = 8;
const MenuProps = {
    PaperProps: {
        style: {
            maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
            width: 250
        }
    }
};

interface Props {
    open: boolean;
    onClose: any;
    payrollGroup?: PayrollGroup;
    onEditPayrollGroup?: any;
}

const PayrollGroupsPopup = (props: Props) => {
    const style = useStyles();

    const { payrollGroup, onEditPayrollGroup, open } = props;

    const [name, setName] = useState<string>('');
    const [types, setTypes] = useState<Array<DisbursementType>>(null);
    const [selectedType, setSelectedType] = useState<string>(null);
    const [disbursementDates, setDisbursementDates] = useState<Array<number>>([]);
    const [minimumPayoutAmount, setMinimumPayoutAmount] = useState<number>();
    const [memberShare, setMemberShare] = useState<number>(100);
    const [loading, setLoading] = useState<boolean>(false);
    const DATES_OF_THE_MONTH = Array.from(Array(31).keys()).map((i) => i + 1);
    const [hasError, setHasError] = useState(false);

    useEffect(() => {
        DisbursementManager.getTypes().then((types: Array<DisbursementType>) => {
            setTypes(types);
            setSelectedType(types[0].name);
        });
    }, []);

    useEffect(() => {
        if (open) {
            if (types?.length) {
                setSelectedType(types[0].name);
            }
            if (payrollGroup) {
                setName(payrollGroup.name);
                setDisbursementDates(payrollGroup.payoutSchedules);
                setMinimumPayoutAmount(payrollGroup.minimumPayoutAmount);
                setMemberShare(payrollGroup.memberShare);
            }
        }
    }, [payrollGroup, open]);

    const onNameChanged = (event) => {
        setHasError(false);
        setName(event.target?.value);
    };

    const onTypeSelected = (event) => {
        setHasError(false);

        if (event.target?.value) {
            setSelectedType(event.target?.value);
        }
    };

    const onDatesSelected = (event: SelectChangeEvent<typeof disbursementDates>) => {
        setHasError(false);
        const value = event.target?.value;
        const dates = typeof value === 'string' ? value.split(',') : value;

        setDisbursementDates(dates as number[]);
    };

    const onMemberSharedChanged = (event) => {
        setHasError(false);
        setMemberShare(event.target?.value);
    };

    const onMinimumPayoutAmountChanged = (event) => {
        setHasError(false);
        const value = Number(event.target?.value);
        setMinimumPayoutAmount(value >= 0 ? value : null);
    };

    const onAddClicked = async () => {
        if (getError() == null) {
            setHasError(false);
            setLoading(true);

            try {
                if (payrollGroup) {
                    const updated = await PayrollGroupManager.update(
                        payrollGroup.id,
                        name,
                        getIDByName(types, selectedType),
                        memberShare,
                        minimumPayoutAmount,
                        disbursementDates
                    );

                    onEditPayrollGroup(updated);
                    clear();
                } else {
                    const copy = await PayrollGroupManager.create(
                        name,
                        getIDByName(types, selectedType),
                        memberShare,
                        minimumPayoutAmount,
                        disbursementDates
                    );

                    props.onClose(copy);
                }
            } catch (e) {
                toast.error(e.message || `Cannot create payroll group!`, { theme: 'dark' });
            } finally {
                setLoading(false);
                props.onClose();
            }
        } else {
            setHasError(true);
        }
    };

    const clear = () => {
        setLoading(false);
        setName(null);
        setSelectedType(null);
        setDisbursementDates([]);
        setMinimumPayoutAmount(null);
    };

    const checkNameForError = (): string => {
        if (name) {
            return null;
        }

        return 'Name is required';
    };

    const checkDisbursementDatesForError = (): string => {
        if (disbursementDates && disbursementDates.length > 0) {
            return null;
        }

        return 'Monthly Disbursement Dates are required';
    };

    const checkMemberShareError = (): string => {
        if (memberShare === null || memberShare === undefined) {
            return 'Member Share is required';
        }

        if (isNaN(memberShare)) {
            return 'Member Share should be a number';
        }

        if (memberShare < 1 || memberShare > 100) {
            return 'Member Share percentage should be between 1 to 100';
        }

        return null;
    };

    const checkMinimumPayoutAmountForError = (): string => {
        if (minimumPayoutAmount === null || minimumPayoutAmount === undefined) {
            return 'Minimum Payout Amount is required';
        }

        if (isNaN(minimumPayoutAmount)) {
            return 'Minimum Payout Amount should be a number';
        }

        if (minimumPayoutAmount < 0) {
            return 'Minimum Payout Amount must greater than 0';
        }

        return null;
    };

    const getError = (): string => {
        if (checkNameForError() != null) {
            return checkNameForError();
        }

        if (checkDisbursementDatesForError() != null) {
            return checkDisbursementDatesForError();
        }

        if (checkMinimumPayoutAmountForError() != null) {
            return checkMinimumPayoutAmountForError();
        }

        if (checkMemberShareError() != null) {
            return checkMemberShareError();
        }

        return null;
    };

    const getTitle = () => {
        return (payrollGroup ? 'Edit' : 'Add') + ' Payroll Group';
    };

    return (
        <GFSDialog open={props.open}>
            <DialogTitle>
                {getTitle()}
                <Box
                    component="img"
                    alt="Icon"
                    src={'/close.svg'}
                    sx={{ cursor: 'pointer' }}
                    onClick={() => props.onClose()}
                />
            </DialogTitle>
            <DialogContent className={`${style.center}`}>
                <Box sx={{ p: 4, pt: 2, width: '100%' }}>
                    {/* Name */}
                    <Box pb={4}>
                        <GfsInputLabel shrink htmlFor="name">
                            Payroll Group Name
                        </GfsInputLabel>
                        <GfsInputBase
                            id="name"
                            onChange={onNameChanged}
                            value={name}
                            placeholder={'Payroll Group Name'}
                        />
                    </Box>

                    {/* Type */}
                    <Box pb={4}>
                        <GfsInputLabel shrink htmlFor="name">
                            Type
                        </GfsInputLabel>
                        <GfsInputSelectBase
                            label="Type"
                            value={selectedType}
                            onChange={onTypeSelected}
                            disabled={!types?.length}
                        >
                            {types &&
                                types.length > 0 &&
                                types.map((type: DisbursementType) => (
                                    <MenuItem
                                        key={type.id}
                                        value={type.name}
                                        className={style.menuItem}
                                    >
                                        <Box
                                            component="img"
                                            sx={{
                                                height: 20,
                                                width: 20,
                                                marginRight: '0.75rem'
                                            }}
                                            alt="Icon"
                                            src={type.icon}
                                        />
                                        {type.name}
                                    </MenuItem>
                                ))}
                        </GfsInputSelectBase>
                    </Box>

                    {/* Monthly Disbursement Dates */}
                    <Box pb={4}>
                        <GfsInputLabel shrink htmlFor="name">
                            Monthly Disbursement Dates
                        </GfsInputLabel>
                        <GfsInputSelectBase
                            label="Monthly Disbursement Dates"
                            multiple
                            value={disbursementDates}
                            onChange={onDatesSelected}
                            placeholder={'Monthly Disbursement Dates'}
                            error={!!checkDisbursementDatesForError()}
                            renderValue={(selected) => (selected as number[]).join(', ')}
                            MenuProps={MenuProps}
                        >
                            {DATES_OF_THE_MONTH &&
                                DATES_OF_THE_MONTH.length > 0 &&
                                DATES_OF_THE_MONTH.map((date: number) => (
                                    <MenuItem key={date} value={date}>
                                        <Checkbox
                                            checked={disbursementDates.indexOf(date) > -1}
                                            sx={{ '& svg': { fill: 'var(--color-dark)' } }}
                                        />
                                        <ListItemText
                                            primary={date}
                                            sx={{ '& *': { color: 'var(--color-dark)' } }}
                                        />
                                    </MenuItem>
                                ))}
                        </GfsInputSelectBase>
                    </Box>

                    {/* Earning Share */}
                    <Typography variant="h6" sx={{ color: '#FFBB59' }}>
                        Earning Share
                    </Typography>

                    <Grid container spacing={2}>
                        <Grid item xs={6}>
                            <Box pt={2} pb={4}>
                                <GfsInputLabel shrink htmlFor="name">
                                    Scholar %
                                </GfsInputLabel>
                                <GfsInputBase
                                    value={memberShare}
                                    onChange={onMemberSharedChanged}
                                    placeholder={'Member Share %'}
                                    type="number"
                                />
                            </Box>
                        </Grid>
                        <Grid item xs={6}>
                            <Box pt={2} pb={4}>
                                <GfsInputLabel shrink htmlFor="name">
                                    Manager %
                                </GfsInputLabel>
                                <Card>
                                    <Typography
                                        sx={{
                                            paddingTop: '10px',
                                            paddingLeft: '20px',
                                            paddingBottom: '10px',
                                            background: '#121029 !important',
                                            color: 'gray'
                                        }}
                                    >
                                        {100 - memberShare}
                                    </Typography>
                                </Card>
                            </Box>
                        </Grid>
                    </Grid>

                    {/* Minimim Payout Amount */}
                    <Box pb={4}>
                        <GfsInputLabel shrink htmlFor="name">
                            Minimum Payout Amount
                        </GfsInputLabel>
                        <GfsInputBase
                            id="name"
                            value={minimumPayoutAmount}
                            onChange={onMinimumPayoutAmountChanged}
                            placeholder={'Minimum Payout Amount. 0 if not applicable'}
                            type="number"
                        />
                    </Box>

                    <GFSLoadingButton
                        sx={{
                            marginTop: '20px',
                            marginBottom: '20px'
                        }}
                        onClick={onAddClicked}
                        loading={loading}
                        fullWidth
                        disabled={!!getError()}
                    >
                        {getTitle()}
                    </GFSLoadingButton>

                    {hasError && (
                        <Alert
                            variant="filled"
                            severity="error"
                            sx={{
                                marginTop: '10px',
                                marginBottom: '20px',
                                background: '#d32f2f !important'
                            }}
                        >
                            {getError()}
                        </Alert>
                    )}
                </Box>
            </DialogContent>
        </GFSDialog>
    );
};

export default PayrollGroupsPopup;
